import JSEncrypt from 'jsencrypt';
import { LOGIN_PUBLIC_KEY } from 'src/utils/constant';
import { v4 as uuidv4 } from 'uuid';
/**
 * @method deepCopy 深拷贝
 * @param {Object}
 *      @param {Object} source : 对象或者数组
 *      @param {Number} maxLevel: 最大拷贝的深度
 *      @param {Number} level:当前拷贝深度
 * @return {Object} 新copy的对象
 *  */
export const deepCopy = (source, maxLevel, level) => {
  const sourceCopy = source instanceof Array ? [] : {};
  for (let key in source) {
    if (level >= maxLevel) {
      sourceCopy[key] = source[key];
      return;
    }
    if (source[key] instanceof Object) {
      sourceCopy[key] = deepCopy(source[key], maxLevel, level++);
    } else {
      sourceCopy[key] = source[key];
    }
  }
  return sourceCopy;
};

/**
 * @method randomKey
 * @description 生成随机字符串id
 * @return {String}
 *  */
export const randomKey = () => uuidv4();

/**
 * @method getCodeByKey
 * @description 获取字符串search中的key=value的value
 * @param {String} search 需要检索的字符串
 * @param {String} key   需要查找的key=的key
 * @return {String}或者null 返回查询到的value,存在则为字符串，否则为null
 *  */
export function getCodeByKey(search, key) {
  const searchGroup = search.replace('?', '').split('&');
  let code = '';
  for (let i = 0; i < searchGroup.length; i++) {
    const keycodes = searchGroup[i].split('=');
    if (keycodes[0] === key) {
      code = keycodes[1];
      break;
    }
  }
  if (code) {
    return code;
  } else {
    return null;
  }
}

/**
 * @method getEncryptCode
 * @description 加密方法，返回加密后的字符串
 * @param {String} code 需要加密的字符串
 * @return {String}或者null 返回加密后的字符串
 *  */
export function getEncryptCode(code) {
  const encrypt = new JSEncrypt();
  encrypt.setPublicKey(LOGIN_PUBLIC_KEY);
  return encrypt.encrypt(code);
}

/**
 * @method getChildTimeUnit
 * @description 获取子时间（包含当前单位）单位，如传入月，返回月、天、小时、分、秒
 * @param {String} currentUnitKey 当前单位 月、天、小时、分、秒的key值
 * @param {Array}  timeUnitsFromCodes 月、天、小时、分、秒组成的对象数组(来自码表的数据)
 * @return {Array} 返回数组
 */
export function getChildTimeUnit(currentUnitKey, timeUnitsFromCodes) {
  //内置的时间，根据后端返回的码表 ，写死在前端, 从左到右具有包含关系，左包含右边全部(顺序一定不能错乱)
  const _units = ['月', '天', '小时', '分', '秒'];
  const currentUnitObj = timeUnitsFromCodes.find((it) => it.key === currentUnitKey); // 从timeUnitsFromCodes中查找出当前对象
  if (currentUnitObj) {
    const currentIndex = _units.findIndex((it) => it === currentUnitObj.value);
    if (currentIndex === -1) {
      return [];
    }
    return _units.reduce((arr, item, index) => {
      if (currentIndex <= index) {
        const timeUnitItem = timeUnitsFromCodes.find((it) => it.value === item);

        timeUnitItem && arr.push(timeUnitItem);
      }
      return arr;
    }, []);
  }
}

/**
 * @method getSeconds
 * @description 获取秒数
 * @param {String} currentUnitKey 当前单位 月、天、小时、分、秒的key值
 * @param {Array}  timeUnitsFromCodes 月、天、小时、分、秒组成的对象数组(来自码表的数据)
 * @param {Number} value 当前时间数值
 * @return {Number} 返回秒数
 */
export function getSeconds(currentUnitKey, timeUnitsFromCodes, value) {
  const currentUnitObj = timeUnitsFromCodes.find((it) => it.key === currentUnitKey); // 从timeUnitsFromCodes中查找出当前对象
  if (currentUnitObj) {
    switch (currentUnitObj.value) {
      case '月':
        return value * 30 * 24 * 60 * 60;
      case '天':
        return value * 24 * 60 * 60;
      case '小时':
        return value * 60 * 60;
      case '分':
        return value * 60;
      case '秒':
        return value;
      default:
        return 0;
    }
  } else {
    return 0;
  }
}

/**
 * @method round
 * @description 四舍五入，保留一个值的n位小数
 * @param {Number} value 数字
 * @param {Number}  n 保留多少位小数,默认2
 * @return {Number} 返回一个四舍五入后，保留n位小数的数字
 */
export function round(value, n = 2) {
  const number = Math.pow(10, n);
  return Math.round(Number(value) * number) / number;
}

/**
 * @method bitTrans
 * @description 将根据，value的值，将bit转换为KB，MB,GB,TB等
 * @param {Number} value
 * @return {Array} [unit,number],number:1KB对应1024bit,1MB:1024*1024
 */
export function bitTrans(value, type) {
  if (value / (1024 * 1024 * 1024) > 1024) {
    return ['T' + type, 1024 * 1024 * 1024 * 1024];
  } else {
    if (value / (1024 * 1024) > 1024) {
      return ['G' + type, 1024 * 1024 * 1024];
    } else {
      if (value / 1024 > 1024) {
        return ['M' + type, 1024 * 1024];
      } else {
        if (value > 1024) {
          return ['K' + type, 1024];
        } else {
          return ['B', 1];
        }
      }
    }
  }
}

/**
 * @method timeTrans
 * @description 将根据，value的值，将时间转换为天时分秒等
 * @param {Number} value
 * @return {String}
 */
export function timeTrans(value) {
  const times_units = [[60 * 60 * 24, '天'], [60 * 60, '时'], [60, '分'], [1, '秒']];
  const times = times_units.reduce(
    ([rest_time, time_str], it) => {
      const time_result = timeTransUnit(rest_time, it);
      return [time_result[0], time_str + time_result[1]];
    },
    [value, '']
  );
  return times[1];
}
function timeTransUnit(value, [unit_number, unit]) {
  if (value / unit_number > 1) {
    const count = Math.floor(value / unit_number);
    const restTime = value - count * unit_number;
    return [restTime, count + unit];
  } else {
    return [value, ''];
  }
}
/**
 * @method lightenDarkenColor
 * @description 根据一个色值，获取他更浅或者更暗的颜色
 * @param {String} col
 * @param {Number} amt
 * @return {String}
 */
//
export function lightenDarkenColor(col, amt) {
  let usePound = false;
  let _col = col;
  if (col[0] === '#') {
    col = col.slice(1);
    usePound = true;
  }
  const num = parseInt(col, 16);
  let r = (num >> 16) + amt;
  if (r > 255) {
    r = 255;
  } else if (r < 0) {
    r = 0;
  }
  let b = ((num >> 8) & 0x00ff) + amt;
  if (b > 255) {
    b = 255;
  } else if (b < 0) {
    b = 0;
  }
  let g = (num & 0x0000ff) + amt;
  if (g > 255) {
    g = 255;
  } else if (g < 0) {
    g = 0;
  }

  const color = (usePound ? '#' : '') + (g | (b << 8) | (r << 16)).toString(16);
  if (usePound && color.length < 7) {
    return _col;
  }

  return color;
}

// 粘贴生成不同规则名
export function createCopyName(name, type, names) {
  // 如果名称相同
  if (names.some((it) => it === name)) {
    const nArr = name.split(type);
    const prevName = nArr[0];
    const nameIndex = nArr.length > 1 ? Number(nArr[1]) + 1 : 1;
    return createCopyName(`${prevName}${type}${nameIndex}`, type, names);
  } else {
    return name;
  }
}

/**
 * @method isRepeatArr
 * @description 判断数组中，某项的key对应的value值是否有重复
 * @param {Array} arr  必填
 * @param {String} key 非必填
 */
export function isRepeatArr(arr, key) {
  let isRepeat = false;
  const obj = {};
  arr.forEach((it) => {
    const k = key ? it[key] : it;
    if (!obj[k]) {
      obj[k] = key ? it[key] : it;
    } else {
      isRepeat = true;
    }
  });
  return isRepeat;
}

/**
 *  @method saveAsJsonFile 保存json文件
 *  @param {Object} data 对象
 *  @param {String} filename json文件名
 */

export function saveAsJsonFile(data, filename) {
  if (!data) {
    alert('保存的数据为空');
    return;
  }
  if (!filename) filename = 'json.json';
  if (typeof data === 'object') {
    data = JSON.stringify(data, undefined, 4);
  }
  var blob = new Blob([data], { type: 'text/json' }),
    e = document.createEvent('MouseEvents'),
    a = document.createElement('a');
  a.download = filename;
  a.href = window.URL.createObjectURL(blob);
  a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
  e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  a.dispatchEvent(e);
}

export const headerModules = (ids) => {
  const modules = [];
  const [first, ...others] = ids.map((it) => it.name);
  if (first) {
    modules[0] = encodeURIComponent(first);
  }
  if (others && others.length > 0) {
    modules[1] = encodeURIComponent(others.join(',').replace(/,$/, ''));
  }
  return modules;
};

/**
 * @method getFeildByTreeData
 * @description 递归查找souceKey对应的对象
 * @param {Array} arr  必填
 * @param {String} souceValue  必填
 * @param {String} souceKey 非必填
 */
export function getFeildByTreeData({ tree, souceKey = 'code', souceVal }) {
  let resultObj;
  if (!tree || !tree.length) return {};
  for (let i = 0; i < tree.length; i++) {
    const item = tree[i];
    if (item[souceKey] === souceVal) {
      resultObj = item;
      break;
    } else if (item.children && item.children.length) {
      resultObj = getFeildByTreeData({ tree: item.children, souceKey, souceVal });
      if (resultObj) return resultObj;
    }
  }
  return resultObj;
}
